/*
 * Copyright 2013 Philip Luyckx
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package be.pluyckx.batteryprogress.activity;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

import be.pluyckx.batteryprogress.R;
import be.pluyckx.batteryprogress.activity.fragment.AdMobFragment;
import be.pluyckx.batteryprogress.activity.fragment.info.calculators.LevelBatteryFragment;
import be.pluyckx.batteryprogress.activity.fragment.info.history.HistoryFragment;
import be.pluyckx.batteryprogress.application.Constants;
import be.pluyckx.batteryprogress.data.history.BatteryHistory;
import be.pluyckx.batteryprogress.logging.LogUtils;
import be.pluyckx.batteryprogress.service.BatteryProgressService;

/**
 * The MainActivity of the application. This activity is viewed first.
 */
public class MainActivity extends FragmentActivity {
  private static final String TAG = "MainActivity";
  private static final String TAG_HISTORY_FRAGMENT = "HistoryFragmentTag";
  private static final String TAG_BATTERY_LEVEL_FRAGMENT = "BatteryLevelFragmentTag";
  private static final String TAG_ADMOB_FRAGMENT = "AdmobFragment";
  private static final Handler mThreadHandler = new Handler();
  private BatteryProgressService mService = null;
  private List<ServiceConnectionListener> mServiceConnectionListeners = new ArrayList<ServiceConnectionListener>();
  private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      mService = ((BatteryProgressService.ServiceBinder) service).getService();
      fireServiceConnected(mService);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
      fireServiceDisconnected();
      mService = null;
    }
  };

  @Override
  protected void onPause() {

    super.onPause();

    unBindService();
  }

  @Override
  protected void onResume() {
    super.onResume();

    bindService();
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.mnu_dump_logcat:
        Constants.logcatDump.dumpFileThreaded(Constants.getDefaultLogcatDumpCallback());
        break;
      case R.id.mnu_dump_history:
        Constants.historyDump.dumpFileThreaded(new BatteryHistory(BatteryHistory.getHistory()),
                Constants.getDefaultHistoryDumpCallback());
        break;
      case R.id.mnu_settings:
        showSettingsActivity();
        break;
      default:
        return super.onOptionsItemSelected(item);
    }

    return true;
  }

  /**
   * Start the settings activity.
   */
  private void showSettingsActivity() {
    Intent startSettingsActivity = new Intent(this, SettingsActivity.class);
    startActivity(startSettingsActivity);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);

    return true;
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
      if (Constants.DEBUG) {
        Log.d(TAG, "Loading landscape view");
      }
      setContentView(R.layout.activity_main_landscape);
    } else {
      if (Constants.DEBUG) {
        Log.d(TAG, "Loading portrait view");
      }
      setContentView(R.layout.activity_main_portrait);
    }

    Fragment fragment = null;

    if (getSupportFragmentManager().findFragmentByTag(TAG_BATTERY_LEVEL_FRAGMENT) == null) {
      if (Constants.DEBUG) {
        Log.d(TAG, "Loading LevelBatteryFragment");
      }
      fragment = new LevelBatteryFragment();
      getSupportFragmentManager().beginTransaction()
              .add(R.id.fragment_level_battery, fragment, TAG_BATTERY_LEVEL_FRAGMENT)
              .commit();
    }


    if (getSupportFragmentManager().findFragmentByTag(TAG_HISTORY_FRAGMENT) == null) {
      if (Constants.DEBUG) {
        Log.d(TAG, "Loading HistoryFragment");
      }
      fragment = new HistoryFragment();
      getSupportFragmentManager().beginTransaction()
              .add(R.id.fragment_history, fragment, TAG_HISTORY_FRAGMENT)
              .commit();
    }

    if (Constants.PUBLIC_RELEASE) {
      if (getSupportFragmentManager().findFragmentByTag(TAG_ADMOB_FRAGMENT) == null) {
        if (Constants.DEBUG) {
          Log.d(TAG, "Loading AdmobFragment");
        }
        fragment = new AdMobFragment();
        getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_admob, fragment, TAG_ADMOB_FRAGMENT)
                .commit();
      }
    } else {
      View view = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
      view.setPadding(view.getPaddingLeft(),
              getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin),
              view.getPaddingRight(),
              view.getPaddingBottom());

      view = findViewById(R.id.fragment_admob);
      view.setPadding(0, 0, 0, 0);
    }
  }

  /**
   * Add a listener to listen to ServiceConnection events
   *
   * @param listener A listener
   */
  public void addServiceConnectionListener(ServiceConnectionListener listener) {
    boolean ret = mServiceConnectionListeners.add(listener);
    if (mService != null) {
      listener.onServiceConnected(mService);
    }

    if (Constants.DEBUG) {
      Log.d(TAG, "Adding listener to MainActivity ServiceItem Connection Listeners: " + listener.toString() + " " + (ret ? "success" : "failed"));
      Log.d(TAG, LogUtils.dumpCollection(mServiceConnectionListeners, this.getClass().getSimpleName()));
    }
  }

  /**
   * Remove a listener from the ServiceConnection events.
   * @param listener
   */
  public void removeServiceConnectionListener(ServiceConnectionListener listener) {
    boolean ret = mServiceConnectionListeners.remove(listener);

    if (Constants.DEBUG) {
      Log.d(TAG, "Removing listener from MainActivity ServiceItem Connection Listeners: " + listener.toString() + " " + (ret ? "success" : "failed"));
      Log.d(TAG, LogUtils.dumpCollection(mServiceConnectionListeners, this.getClass().getSimpleName()));
    }
  }

  /**
   * Fire the onServiceConnected event to all listeners.
   * @param binder The Service binder
   */
  protected void fireServiceConnected(BatteryProgressService binder) {
    for (ServiceConnectionListener l : mServiceConnectionListeners) {
      l.onServiceConnected(binder);
    }
  }

  /**
   * fire the onServiceDisconnected event to all listeners.
   */
  protected void fireServiceDisconnected() {
    for (ServiceConnectionListener l : mServiceConnectionListeners) {
      l.onServiceDisconnected();
    }
  }

  /**
   * Bind to the Service.
   */
  private void bindService() {
    Intent service = BatteryProgressService.createIntentBind(this);
    bindService(service, mServiceConnection, BIND_AUTO_CREATE);
  }

  /**
   * Disconnect from the Service and update all listeners.
   */
  private void unBindService() {
    fireServiceDisconnected();
    unbindService(mServiceConnection);
    mService = null;
  }

  /**
   * Listeners for ServiceConnection events must implement this interface.
   */
  public static interface ServiceConnectionListener {
    /**
     * When connected to the Service
     * @param service the Service which is connected
     */
    public void onServiceConnected(BatteryProgressService service);

    /**
     * When the connection to a Service is lost.
     */
    public void onServiceDisconnected();
  }
}
